package com.thomas.framework.web.interceptor;

import com.thomas.framework.core.AppException;
import com.thomas.framework.core.annotation.Function;
import com.thomas.framework.core.annotation.FunctionMenu;
import com.thomas.framework.entity.SysModel;
import com.thomas.framework.entity.SysUser;
import com.thomas.framework.utils.CommonUtil;
import com.thomas.framework.utils.JsonUtil;
import com.thomas.framework.utils.ReflectUtil;
import com.thomas.framework.utils.WebContext;
import org.apache.log4j.Logger;
import org.aspectj.lang.ProceedingJoinPoint;
import org.springframework.aop.ProxyMethodInvocation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.ResponseBody;

import javax.servlet.http.HttpSession;
import java.lang.reflect.Method;
import java.util.Date;
import java.util.List;
import java.util.Map;

/**
 * 访问控制类
 * Created by taohj on 2014/5/25.
 */
public class AccessControlHandlerAdapter {

    Logger logger = Logger.getLogger(getClass());

    private List<String> allowUrls;


    @Autowired
    private  WebContext context;


    public void setAllowUrls(List<String> allowUrls) {
        this.allowUrls = allowUrls;
    }


    @SuppressWarnings("unchecked")
    public Object invoke(ProceedingJoinPoint obj) throws Throwable {
        ProxyMethodInvocation methodInvocation = (ProxyMethodInvocation) ReflectUtil.getFieldValue(obj, "methodInvocation");
        Method method = methodInvocation.getMethod();

        Function functionAnnotation = method.getAnnotation(Function.class);
        FunctionMenu functionMenuAnnotation = method.getDeclaringClass().getAnnotation(FunctionMenu.class);
        HttpSession session = WebContext.getHttpSession();
        Object [] objects =  obj.getArgs();
        Map<String, SysModel> functions = (Map<String, SysModel>) session.getAttribute("functions");


        StringBuilder bf = new StringBuilder();
        bf.append("[").append(CommonUtil.dateFormateSS(new Date())).append("]");


        SysUser user = (SysUser) session.getAttribute("user");



        if ((!checkallUrl((WebContext.getHttpServletRequest().getRequestURI())))  && user == null) {

            String message="You are not logged in, login or has timed out, please <a href='javascript:location.href=\"admin\";' >click here</a> login again !";
            return  this.sendMessage(method,message);
        }




        if (!checkallUrl(WebContext.getHttpServletRequest().getRequestURI()) && user != null) {


            if (checkAccess(functionAnnotation)){
                throw new AppException("You do not have permission to access");
            }


            bf.append("<<").append(user.getUserName()).append(">>");

            if (functions != null) {

                if (functionMenuAnnotation != null) {
                    SysModel functionMenu = functions.get(functionMenuAnnotation.value());
                    if (functionMenu != null) {
                        bf.append("================>").append(functionMenu.getDescription());
                    }
                }else{
                    throw new AppException("This method is not registered:"+method.getName());
                }

                if (functionAnnotation != null) {
                    SysModel function = functions.get(functionAnnotation.value());
                    if (function != null) {
                        bf.append("-->").append(function.getDescription());
                    }
                }
            }

            bf.append("~~~>").append(JsonUtil.toString(WebContext.getHttpServletRequest().getParameterMap()));
            logger.info(bf.toString());
        }
        return obj.proceed();
    }


    private boolean checkallUrl(String url) {

        String contextPath=WebContext.getHttpServletRequest().getContextPath();

        for (String u : allowUrls) {
            if (( contextPath+u).equals(url)) {
                return true;
            }
        }
        return false;
    }

    private boolean checkMethod(Method method) {
        return method.getAnnotation(ResponseBody.class) != null;
    }


    protected boolean checkAccess(Function function){
        Map<String,SysModel> functions= context.getAdmin().getFunctions();

       SysModel model=functions.get(function.value());

        return  model==null;
    }


    private String sendMessage(Method method,String message){

        if (checkMethod(method)){
            throw new AppException(message);
        }else {
               // WebContext.getHttpServletRequest().get
            return "redirect:/admin";
        }


    }

}
